import * as Cesium from "cesium";
import { cesiumInit, getViewer } from "./cesiumInit";
import {
  DrawPointPicture,
  DrawPolymerizationPointPicture,
} from "./drawPointPicture";
import { sceneModeToggle } from "./sceneModeToggle";
import { colorArray } from "./utils/colorArray";
import { wgs84togcj02, gcj02toWgs84 } from "@utils";
import {
  addArcGISLayer,
  addBingMapLayer,
  addDEMLayer,
  addGoogleLayer,
  addIonLayer,
  addMapBoxLayer,
  addmfsLayer,
  addMvtLayer,
  addOsmLayer,
  addS3MLayer,
  addSingleLayer,
  addTemplateImagery,
  addTileMapServiceLayer,
  addTmsLayer,
  addWmLayer,
  addWmsLayer,
  addWmtsLayer,
  removeImageryLayer,
  displayHideLayer,
} from "./addLayer"; // 瓦片
import {
  AcquisitionLine,
  DrawPolyLine,
  DrawRailwayLine,
  EditPolyLine,
  HorizontalStreamline,
  RadianFlyingLine,
  VerticalStreamline,
} from "./line";
import {
  DrawPolygon,
  DrawPolygonChartlet,
  EditPolygon,
  PolygonDrawingTool,
} from "./polygon";
import { DrawRound, AcquisitionRound, EditRound } from "./round";
import { flyTo, flyToBoundingSphere, lookAt, setView } from "./camera";
import { FilterLensLayer } from "./filter";
import { renderBinGltf, renderGlb, renderGltf } from "./render3d";
import { Heatmap2D, Heatmap3D } from "./heatMap";
import { Popup } from "./popup";
import { DrawWall } from "./wall";
import { convertToCoordinatePairs } from "./utils/convertToCoordinatePairs";
export { cesiumInit };

export interface MapAPI {
  viewer: Cesium.Viewer;
  Cesium: typeof Cesium;
  //utils
  gcj02toWgs84: typeof gcj02toWgs84; // gcj02 转换 wgs84
  wgs84togcj02: typeof wgs84togcj02; // wgs84 转换 gcj02
  colorArray: typeof colorArray; // 获取颜色数组
  convertToCoordinatePairs: typeof convertToCoordinatePairs; // 转换为坐标对
  // Layer
  addWmtsLayer: typeof addWmtsLayer; // 渲染 wmts 图层
  addWmsLayer: typeof addWmsLayer; //   渲染 wms 图层
  addTemplateImagery: typeof addTemplateImagery; // 渲染 UrlTemplate 图层
  removeImageryLayer: typeof removeImageryLayer; // 删除影像图层
  addWmLayer: typeof addWmLayer; // 渲染 wm 图层
  addMvtLayer: typeof addMvtLayer; // 渲染 mvt 图层
  addDEMLayer: typeof addDEMLayer; // 渲染 DEM 图层
  addArcGISLayer: typeof addArcGISLayer; // 渲染 ArcGIS 图层
  addBingMapLayer: typeof addBingMapLayer; // 渲染 BingMap 图层
  addMapBoxLayer: typeof addMapBoxLayer; // 渲染 MapBox 图层
  addSingleLayer: typeof addSingleLayer; // 渲染 Single 图层
  addS3MLayer: typeof addS3MLayer; // 渲染 S3M 图层
  addGoogleLayer: typeof addGoogleLayer; // 渲染 Google 图层
  addmfsLayer: typeof addmfsLayer; // 渲染 mfs 图层
  addOsmLayer: typeof addOsmLayer; // 渲染 osm 图层
  addIonLayer: typeof addIonLayer; // 渲染 ion 图层
  addTileMapServiceLayer: typeof addTileMapServiceLayer; // 渲染 TileMapService 图层
  displayHideLayer: typeof displayHideLayer; // 显示隐藏图层
  addTmsLayer: typeof addTmsLayer; // 渲染  Tms 图层
  sceneModeToggle: typeof sceneModeToggle; // 切换地图模式
  // camera
  flyToBoundingSphere: typeof flyToBoundingSphere;
  flyTo: typeof flyTo;
  lookAt: typeof lookAt;
  setView: typeof setView;
  // 3d模型加载
  renderGltf: typeof renderGltf; // TODO:
  renderBinGltf: typeof renderBinGltf; // TODO:
  renderGlb: typeof renderGlb; // TODO:
  // class
  DrawPolyLine: typeof DrawPolyLine; // 绘制实/虚线
  DrawRailwayLine: typeof DrawRailwayLine; //绘制铁路线
  VerticalStreamline: typeof VerticalStreamline; //垂直流线
  DrawPolygon: typeof DrawPolygon; // 绘制多边形
  AcquisitionLine: typeof AcquisitionLine; // 采集线
  DrawPolygonChartlet: typeof DrawPolygonChartlet; // 多边形贴图
  DrawRound: typeof DrawRound; // 绘制圆
  DrawPointPicture: typeof DrawPointPicture; //绘制点图(基本)
  DrawPolymerizationPointPicture: typeof DrawPolymerizationPointPicture; //绘制聚合点图片 // TODO: 未完成
  EditPolygon: typeof EditPolygon; // 编辑边形  // TODO: 未完成
  AcquisitionRound: typeof AcquisitionRound; // 采集多边形
  PolygonDrawingTool: typeof PolygonDrawingTool; // 采集多边形  // TODO: 可以使用，但是需要优化
  EditRound: typeof EditRound; // 采集多边形  // TODO: 未完成
  HorizontalStreamline: typeof HorizontalStreamline; //水平流线 // TODO: 未完成
  EditPolyLine: typeof EditPolyLine; //编辑线 // TODO: 未完成
  RadianFlyingLine: typeof RadianFlyingLine; //弧度飞线 // TODO: 未完成
  FilterLensLayer: typeof FilterLensLayer; // 滤镜图层
  Heatmap2D: typeof Heatmap2D;
  Heatmap3D: typeof Heatmap3D;
  Popup: typeof Popup;
  DrawWall: typeof DrawWall;
}
// 最大尝试次数
const MAXIMUM_ATTEMPTS = 25;

export const cesiumMapAPI = (): Promise<MapAPI> =>
  new Promise<MapAPI>((resolve, reject) => {
    let counter = 0;
    let interval: number | undefined | NodeJS.Timeout;
    const checked = () => {
      const viewer = getViewer();
      if (counter > MAXIMUM_ATTEMPTS) {
        if (typeof interval === "number") {
          clearInterval(interval);
        }
        reject(new Error("地图实例未初始化"));
      } else if (viewer instanceof Cesium.Viewer) {
        const apis = {
          viewer,
          Cesium,
          gcj02toWgs84,
          wgs84togcj02,
          convertToCoordinatePairs,
          colorArray,
          sceneModeToggle,
          addArcGISLayer,
          addBingMapLayer,
          addDEMLayer,
          addGoogleLayer,
          addIonLayer,
          addMapBoxLayer,
          addmfsLayer,
          addMvtLayer,
          addOsmLayer,
          addS3MLayer,
          addSingleLayer,
          addTemplateImagery,
          addTileMapServiceLayer,
          addTmsLayer,
          addWmLayer,
          addWmsLayer,
          addWmtsLayer,
          removeImageryLayer,
          displayHideLayer,
          flyToBoundingSphere,
          flyTo,
          lookAt,
          setView,
          renderGltf,
          renderBinGltf,
          renderGlb,
          DrawPolyLine,
          DrawPointPicture,
          DrawRailwayLine,
          EditPolyLine,
          VerticalStreamline,
          DrawPolygon,
          EditPolygon,
          DrawPolygonChartlet,
          PolygonDrawingTool,
          DrawRound,
          AcquisitionRound,
          EditRound,
          HorizontalStreamline,
          RadianFlyingLine,
          AcquisitionLine,
          DrawPolymerizationPointPicture,
          FilterLensLayer,
          Heatmap2D,
          Heatmap3D,
          Popup,
          DrawWall,
        };
        if (typeof interval === "number") {
          clearInterval(interval);
        }
        resolve(apis);
      } else {
        console.log(`尝试初始化地图地${counter}次`);
        counter += 1;
      }
    };
    checked();
    if (counter > 0) {
      interval = setInterval(() => checked(), 250);
    }
  });
